// Copyright 2012 Ray Lambert <codemonkey@interthingy.net>
// Licensed under GPLv3+ or later (see COPYING)
// hosted at: http://code.google.com/p/argent/

#ifndef __regex_h__
#define __regex_h__

#include <regex.h>
#include <vector>
#include <string>

class regex
{
protected:
    regex_t exp;

    bool throw_error(int rc) const;

public:
    typedef std::vector<regmatch_t> results;
    static const unsigned extended = 0x01;
    static const unsigned nocase   = 0x02;

    regex(const std::string &s, unsigned flags=0);
    ~regex();

    /// Executes the regular expression on string @p s starting at offset @p
    /// ofs.  Results are stored in @p r and @c true is returned if at least one
    /// match is found.  The first element returned in @p r represents the full
    /// matching string and any additional elements represent group matches.  In
    /// this overload the results are returned as a set of offsets into @p s, as
    /// defined by libregex.
    /// @see man regex
    bool exec(const std::string &s, results &r, std::string::size_type ofs=0) const;

    /// Executes the regular expression on string @p s starting at offset @p
    /// ofs.  Results are stored in @p r and @c true is returned if at least one
    /// match is found.  The first element returned in @p r represents the full
    /// matching string and any additional elements represent group matches.  In
    /// this overload the results are returned as plain strings.
    bool exec(const std::string &s, std::vector<std::string> &r, std::string::size_type ofs=0) const;

    /// Performs a substitution similar sed and vi.  @p rep is the replacement
    /// string and serves effectively as a template for formatting the output.
    /// @p s is the original string and @p res describes the matching sub-fields
    /// within @p s.  The first element in @p res represents the full sub-string
    /// of @p s that matched the pattern.  Any additional elements represent
    /// group matches.  If @p whole is @c true then the non-matched leading and
    /// trailing portions of @p s (if any) are output with the expansion of @p
    /// rep between them, otherwise only the expansion of @p rep is output.
    /// 
    /// @p rep may contain group references consisting of a backslash followed
    /// by a digit.  A exception is thrown for a reference to a non-existent
    /// group.  The sequence '\0' references the full matching sub-string.
    ///
    /// @p rep may also contain the special operators, '\U' (upper case), '\L'
    /// (lower case) and '\W' (word case), which change the alphabetic case of
    /// the text of the next referenced group.
    ///
    /// @p rep may also contain the following common escape sequences that
    /// produce control characters: '\n' (newline), '\r' (return), '\t' (tab),
    /// '\f' (form feed), '\b' (backspace) and '\z' (ASCII 0).
    static std::string subst(const std::string &s, const results &res, const std::string &rep, bool whole=false);

    /// Performs a substitution like subst(const std::string &, const results &,
    /// const std::string &, bool whole) except that it takes a vector of
    /// literal strings instead of a @em results object.  Note that the zeroth
    /// element of @p matches is expected to be a string that represents the
    /// full match against @p s (i.e. the '\0' reference) just as the
    /// aforementioned overload.  Additionally, this overload cannot identify
    /// the non-matched leading and trailing portions of @p s and therefore does
    /// not output them.
    static std::string subst(const std::string &s, const std::vector<std::string> &matches, const std::string &rep);
};

#endif

